/*  This head file can transfer floating/double point number to integer, and vice verse.
 *  member function I2D transfers integer to decimal. 
 *  member function D2I transfers decimal to integer.
 *  WordSize is the size of integer,
 *  FractionSize is the size of fraction part in number.
*/
#include <cmath>
#include <cassert>

template <class T>
class NumberTransform
{
    int WordSize;
    int FractionSize;
public:
    NumberTransform(int GivenWordSize, int GivenFractionSize);
    ~NumberTransform();
    double I2D(T Integer);
    T D2I(double Double); 
};

template<class T>
NumberTransform<T>::NumberTransform(int GivenWordSize, int GivenFractionSize) 
{
    WordSize = GivenWordSize;
    FractionSize = GivenFractionSize;
    assert (WordSize >= FractionSize);
}

template<class T>
NumberTransform<T>::~NumberTransform() {}

template<class T>
double NumberTransform<T>::I2D(T Integer) 
{
    double Decimal = 0.0;
    if (Integer == 0)
        return 0.0;

    bool Positive_Flag = true;
    if (Integer < 0) {
        Positive_Flag = false;
        Integer = abs(Integer);
    }
    int One_Bit = 1;
    int Shift_One_Bit = 0;
    double Fraction_Sum = 0.0;
    int Int_Number = 0;
    int Temp_Number = 0;
    int Fraction_Number = 0;
    Temp_Number = int(Integer) >> FractionSize;  //  right shift fractionsize to get real integer part.
    Int_Number = Temp_Number << FractionSize;
    Fraction_Number = int(Integer) - Int_Number;  //  Get the fraction number.
    for (int i = 0; i < FractionSize; i++) {  //  Get the fraction number.
        Shift_One_Bit = One_Bit << (FractionSize-i-1);
        Shift_One_Bit &= Fraction_Number;
        if (Shift_One_Bit != 0)
            Fraction_Sum += pow(2.0,(-1-i));
    }
    Decimal = double(Int_Number) + Fraction_Sum;  //  integer part plus fraction part to get decimal.
    if (Positive_Flag == false)
       Decimal = 0 - Decimal;
    return Decimal;
}

template<class T>
T NumberTransform<T>::D2I(double Double_Number) 
{
    int Integer = 0;
    if (Double_Number == 0.0)
        return Integer;

    bool Positive_Flag = true;
    if (Double_Number < 0) {
        Positive_Flag = false;
        Double_Number = fabs(Double_Number);
    }
    double Fraction = 0.0;
    double Max_Num = 0;
    int Int_Size = 0;
    int Int_Part = 0;
    int Max_Bit = 0;
    int One_Bit = 1;
    int Shift_One_Bit = 0;
    int Fraction_Sum = 0;
    int Int_Number = 0;

    Int_Part = int(Double_Number);  //  Get the integer part from the decimal.
    Fraction = Double_Number - double(Int_Part);  //  Get the fraction part from the decimal.
    Int_Size = WordSize - FractionSize;  //  Get the integer part size.
    Max_Num = pow(2.0,Int_Size);  //  Get the maximum number with the Int_Size.

    //  Make sure no exceeding the maximum number.
    if (Positive_Flag)
        assert(Double_Number < Max_Num);
    else
        assert(Double_Number <= Max_Num);
	
    Int_Number = Int_Part << FractionSize;  //  Left shift the Int_Part to get the integer number.

    for (int i = 0; i < FractionSize; i++) {  //  Convert fraction part to integer. ie, 0.5 --> 1.
        Max_Bit = int(Fraction * 2);
        if (Max_Bit != 0) {
            Shift_One_Bit = One_Bit << (FractionSize-i-1);
            Fraction_Sum |= Shift_One_Bit;
        }
        Fraction = Fraction*2 - double(Max_Bit);
    }

    Integer = Int_Number | Fraction_Sum;  //  integer part plus fraction part to get converted integer.
    if (Positive_Flag == false)
        Integer = 0 - Integer;
    return T(Integer);
}
